"""Hydrology forecast analysis logic."""

from typing import Dict, Any, List, Optional, Tuple
from datetime import datetime
import statistics


class ForecastAnalyzer:
    """Analyzer for hydrology forecast data."""
    
    def __init__(self, forecast_data: Dict[str, Any]):
        """
        Initialize analyzer with forecast data.
        
        Args:
            forecast_data: Complete forecast data from API
        """
        self.data = forecast_data
        self.real_data = forecast_data.get("data", {}).get("real_data", {})
        self.hypothetical_data = forecast_data.get("data", {}).get("hypothetical_data", [])
    
    def get_session_info(self) -> Dict[str, Any]:
        """
        Get basic session information.
        
        Returns:
            Dict with session metadata
        """
        return {
            "session_id": self.real_data.get("session_id"),
            "station_code": self.real_data.get("stcd"),
            "station_name": self.real_data.get("stcd_name"),
            "model_type": self.real_data.get("model_type"),
            "model_chain": self.real_data.get("model_chain", {}).get("description"),
            "num_hypothetical": len(self.hypothetical_data)
        }
    
    def get_model_parameters(self) -> Dict[str, Any]:
        """
        Get model parameters.
        
        Returns:
            Dict with model parameters
        """
        models = self.real_data.get("models", [])
        if not models:
            return {}
        
        model = models[0]
        return {
            "model_name": model.get("name"),
            "model_type": model.get("type"),
            "parameters": model.get("parameters", {}),
            "initial_state": model.get("initial_state", {})
        }
    
    def _extract_timeseries(self, forecast_item: Dict[str, Any]) -> List[Dict[str, Any]]:
        """
        Extract timeseries data from forecast item.
        
        Args:
            forecast_item: Either real_data or one hypothetical forecast
            
        Returns:
            List of timeseries points (after start_time, excluding warmup)
        """
        # 空值检查
        if not forecast_item or not isinstance(forecast_item, dict):
            return []
        
        # 正确的路径: forecast_result -> timeSeries
        forecast_result = forecast_item.get("forecast_result")
        if not forecast_result or not isinstance(forecast_result, dict):
            return []
        
        time_series = forecast_result.get("timeSeries", [])
        
        if not time_series:
            return []
        
        # 获取 start_time，过滤掉预见期之前的数据
        start_time = forecast_item.get("start_time", "")
        
        # 过滤：1) 不是warmup 2) 时间在start_time之后
        filtered_series = []
        for point in time_series:
            if point.get("isWarmUp", False):
                continue
            # 如果有start_time，只取start_time之后的数据
            if start_time and point.get("time", "") < start_time:
                continue
            filtered_series.append(point)
        
        return filtered_series
    
    def calculate_flood_metrics(self, forecast_item: Dict[str, Any]) -> Dict[str, Any]:
        """
        Calculate flood metrics: volume, peak discharge, peak time.
        
        Args:
            forecast_item: Either real_data or one hypothetical forecast
            
        Returns:
            Dict with flood metrics
        """
        # 空值检查
        if not forecast_item:
            return {
                "error": "预报数据为空，请检查会话ID是否正确"
            }
        
        timeseries = self._extract_timeseries(forecast_item)
        
        if not timeseries:
            # 提供更详细的错误信息
            has_forecast_result = bool(forecast_item.get("forecast_result"))
            return {
                "error": f"未找到时间序列数据 (forecast_result存在: {has_forecast_result})"
            }
        
        # Extract Q (discharge) values and times
        # DHF 模型中的流量字段是 QSim
        
        discharges = []
        times = []
        
        for point in timeseries:
            time = point.get("time")
            # DHF 模型的流量字段：QSim
            q = point.get("QSim")
            
            # 备选字段
            if q is None:
                q = point.get("Q") or point.get("discharge") or point.get("flow")
            
            if time and q is not None:
                discharges.append(float(q))
                times.append(time)
        
        if not discharges:
            return {
                "flood_volume": None,
                "peak_discharge": None,
                "peak_time": None,
                "error": "No discharge data found"
            }
        
        # Calculate metrics
        peak_discharge = max(discharges)
        peak_idx = discharges.index(peak_discharge)
        peak_time = times[peak_idx]
        
        # Flood volume: sum of discharge * time interval (assuming 3-hour intervals)
        # Convert to m³ (discharge in m³/s * 3600s/h * 3h)
        time_interval_hours = 3
        flood_volume = sum(discharges) * 3600 * time_interval_hours
        
        return {
            "flood_volume_m3": round(flood_volume, 2),
            "peak_discharge_m3s": round(peak_discharge, 2),
            "peak_time": peak_time,
            "num_points": len(discharges),
            "start_time": times[0] if times else None,
            "end_time": times[-1] if times else None,
            "avg_discharge_m3s": round(statistics.mean(discharges), 2)
        }
    
    def analyze_real_forecast(self) -> Dict[str, Any]:
        """
        Analyze real forecast metrics.
        
        Returns:
            Dict with real forecast analysis
        """
        return {
            "type": "real",
            "session_info": self.get_session_info(),
            "metrics": self.calculate_flood_metrics(self.real_data)
        }
    
    def analyze_hypothetical_forecast(self, index: int) -> Dict[str, Any]:
        """
        Analyze a specific hypothetical forecast.
        
        Args:
            index: Index of hypothetical forecast (0-based)
            
        Returns:
            Dict with hypothetical forecast analysis
        """
        if index < 0 or index >= len(self.hypothetical_data):
            return {"error": f"Invalid index {index}. Available: 0-{len(self.hypothetical_data)-1}"}
        
        hyp = self.hypothetical_data[index]
        return {
            "type": "hypothetical",
            "index": index,
            "name": hyp.get("name", f"Hypothetical-{index}"),
            "description": hyp.get("description", ""),
            "metrics": self.calculate_flood_metrics(hyp)
        }
    
    def analyze_all_hypothetical(self) -> List[Dict[str, Any]]:
        """
        Analyze all hypothetical forecasts.
        
        Returns:
            List of analyses for all hypothetical forecasts
        """
        return [
            self.analyze_hypothetical_forecast(i) 
            for i in range(len(self.hypothetical_data))
        ]
    
    def compare_forecasts(self) -> Dict[str, Any]:
        """
        Compare real forecast with all hypothetical forecasts.
        
        Returns:
            Dict with comparison results
        """
        real_analysis = self.analyze_real_forecast()
        real_metrics = real_analysis["metrics"]
        
        if "error" in real_metrics:
            return {"error": "Cannot analyze real forecast", "details": real_metrics}
        
        comparisons = []
        
        for i, hyp in enumerate(self.hypothetical_data):
            hyp_analysis = self.analyze_hypothetical_forecast(i)
            hyp_metrics = hyp_analysis["metrics"]
            
            if "error" in hyp_metrics:
                comparisons.append({
                    "index": i,
                    "name": hyp.get("name", f"Hypothetical-{i}"),
                    "error": hyp_metrics["error"]
                })
                continue
            
            # Calculate differences
            volume_diff = hyp_metrics["flood_volume_m3"] - real_metrics["flood_volume_m3"]
            peak_diff = hyp_metrics["peak_discharge_m3s"] - real_metrics["peak_discharge_m3s"]
            
            # Calculate percentage differences
            volume_pct = (volume_diff / real_metrics["flood_volume_m3"] * 100) if real_metrics["flood_volume_m3"] != 0 else 0
            peak_pct = (peak_diff / real_metrics["peak_discharge_m3s"] * 100) if real_metrics["peak_discharge_m3s"] != 0 else 0
            
            comparisons.append({
                "index": i,
                "name": hyp.get("name", f"Hypothetical-{i}"),
                "description": hyp.get("description", ""),
                "differences": {
                    "flood_volume": {
                        "hypothetical": hyp_metrics["flood_volume_m3"],
                        "real": real_metrics["flood_volume_m3"],
                        "difference_m3": round(volume_diff, 2),
                        "difference_percent": round(volume_pct, 2)
                    },
                    "peak_discharge": {
                        "hypothetical": hyp_metrics["peak_discharge_m3s"],
                        "real": real_metrics["peak_discharge_m3s"],
                        "difference_m3s": round(peak_diff, 2),
                        "difference_percent": round(peak_pct, 2)
                    },
                    "peak_time": {
                        "hypothetical": hyp_metrics["peak_time"],
                        "real": real_metrics["peak_time"],
                        "same": hyp_metrics["peak_time"] == real_metrics["peak_time"]
                    }
                }
            })
        
        return {
            "real_forecast": real_metrics,
            "num_hypothetical": len(self.hypothetical_data),
            "comparisons": comparisons,
            "summary": self._generate_comparison_summary(comparisons)
        }
    
    def _generate_comparison_summary(self, comparisons: List[Dict[str, Any]]) -> Dict[str, Any]:
        """Generate summary statistics for comparisons."""
        if not comparisons or any("error" in c for c in comparisons):
            return {"note": "Some forecasts have errors"}
        
        volume_diffs = [c["differences"]["flood_volume"]["difference_percent"] for c in comparisons]
        peak_diffs = [c["differences"]["peak_discharge"]["difference_percent"] for c in comparisons]
        
        return {
            "volume_diff_range": {
                "min_percent": round(min(volume_diffs), 2),
                "max_percent": round(max(volume_diffs), 2),
                "avg_percent": round(statistics.mean(volume_diffs), 2)
            },
            "peak_diff_range": {
                "min_percent": round(min(peak_diffs), 2),
                "max_percent": round(max(peak_diffs), 2),
                "avg_percent": round(statistics.mean(peak_diffs), 2)
            }
        }

